<?php
/**
 * Description:
 * Author: hezhizheng
 * Date: 2018/10/16
 * Time: 16:14
 * Created by Created by Panxsoft.
 */

namespace App\Services\Utils;

use App\Models\Logger\LogType;
use App\Models\Logger\OperateLog;
use Illuminate\Database\Eloquent\Model;

/**
 * @link https://www.jianshu.com/p/5eb77375954d
 *
 * Trait ActionLogger
 *
 * @package App\Services\Utils
 *
 * @mixin Model
 */
trait ActionLogger
{
    /**
     * 处理模型事件
     */
    protected static function bootActionLogger()
    {
        foreach (static::getModelEvents() as $event) {
            static::$event(function (Model $model) use ($event) {
                self::createActionLogByEvent($model, $event);
            });
        }
    }

    /**
     * @param Model $model
     * @param string $event
     *
     * @return OperateLog|null
     */
    protected static function createActionLogByEvent(Model $model, string $event): ?OperateLog
    {
        $operator_user = Guard::operatorUser();
        if (!$operator_user) {
            return null;
        }

        if (!in_array($event, self::defaultActionLogEvents())) {
            return null;
        }

        /** @var self $model */
        $description = $model->getActionDescription($model, $event);

        $log = $event . '：' . class_basename($model);

        return OperateLog::createLog(
            $operator_user, $model,
            LogType::OPERATE_BOOT_EVENT, $log,
            $operator_user->customer_id ?? 0,
            $operator_user->store_id ?? 0,
            $event, $description
        );
    }

    /**
     * 获取要响应的模型事件
     * @return array
     */
    protected static function getModelEvents(): array
    {
        if (isset(static::$recordEvents)) {
            return static::$recodrdEvents;
        }

        return self::defaultActionLogEvents();
    }


    /**
     * 获取模型事件描述
     * @param self|Model $model
     * @param $event
     * @return array
     */
    protected function getActionDescription(Model $model, string $event): array
    {
        if (method_exists($this, 'getCustomActionDescription')) {
            return $this->getCustomActionDescription($model, $event);
        }

        return $this->assembleActionDescription($model, $event);
    }


    /**
     * @param Model $model
     * @param string $event
     * @return array
     */
    protected function assembleActionDescription(Model $model, string $event): ?array
    {
        $description = $model->toArray();

        if ($event === 'updated') {
            $description = [
                'original' => array_intersect_key($model->getOriginal(), $model->getDirty()),
                'dirty'    => $model->getDirty()
            ];
        }

        return $description;
    }

    /**
     * @return array
     */
    protected static function defaultActionLogEvents(): array
    {
        return ['created', 'updated', 'deleted'];
    }

}